/**
  \file dawg_arr_template.h
  \author Francis Girard
  \date 30 september 2013

  Dawg array template.

  For example, if you want an array of schmilbliks
  the type of which are int. You may define in a
  header file like this:

  // dawg_arr_schmilbliks.h

  #ifndef __dawg_arr_schmilbliks_h__
  #define __dawg_arr_schmilbliks_h__

  #ifdef _NAME_
  #undef _NAME_
  #endif

  #ifdef _TYPE_
  #undef _TYPE_
  #endif

  #define _NAME_ schmilbliks
  #define _TYPE_ int

  #include "dawg_arr_template.h"

  #endif

  And a .c file like this:

  // dawg_arr_schmilbliks.c
  #define _NAME_ schmilbliks
  #define _TYPE_ int
  #include "dawg_arr_template.c"
*/


/*
 *  Copyright (C) 2013, Francis Girard
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


// Don't do this (this is a code template) :
// #ifndef __dawg_arr_template_h__
// #define __dawg_arr_template_h__

#include "dawg_types.h"

//
// Type Name Macros
//
#define H_DAWG_ARR_TYPE_DEF(name) h_dawg_arr_##name
#define H_DAWG_ARR_TYPE(name)     H_DAWG_ARR_TYPE_DEF(name)
#define H_DAWG_ARR_TYPE_NAME      H_DAWG_ARR_TYPE(_NAME_)
    // H_DAWG_ARR_TYPE_NAME where _NAME_ is for example void_ptr will expand into:
    // h_dawg_arr_void_ptr


//
// Function Name Macros
//
#define DAWG_ARR_FUNC_DEF(LITT_TYPE, FUNC_NAME) dawg_arr_##LITT_TYPE##_##FUNC_NAME
#define DAWG_ARR_FUNC(LITT_TYPE, FUNC_NAME)     DAWG_ARR_FUNC_DEF(LITT_TYPE, FUNC_NAME)
#define DAWG_ARR_FUNC_NAME(FUNC_NAME)           DAWG_ARR_FUNC(_NAME_, FUNC_NAME)
    // DAWG_ARR_FUNC_NAME(create) and _NAME_ is "void_ptr" will expand into:
    //              dawg_arr_void_ptr_create


//
// Iterator Type Name Macros
//
#define H_DAWG_ARR_IT_TYPE_DEF(name) h_dawg_arr_##name##_it
#define H_DAWG_ARR_IT_TYPE(name)     H_DAWG_ARR_IT_TYPE_DEF(name)
#define H_DAWG_ARR_IT_TYPE_NAME      H_DAWG_ARR_IT_TYPE(_NAME_)
    // H_DAWG_ARR_IT_TYPE_NAME where _NAME_ is for example void_ptr will expand into:
    // h_dawg_arr_it_void_ptr


///////////////////////////////////////
///////////////////////////////////////
//                                   //
// extern C BEGIN                    //
//                                   //
///////////////////////////////////////
///////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif

/// Handle on the array.
typedef void* H_DAWG_ARR_TYPE_NAME;

/// Handle on an iterator.
typedef _TYPE_* H_DAWG_ARR_IT_TYPE_NAME;


/**
  Create an empty array and without preallocated memory.
  @return A handle on the new array.
  */
H_DAWG_ARR_TYPE_NAME DAWG_ARR_FUNC_NAME(create)();


/**
  Create an empty array but _with_ preallocated memory.
  @param nInitialCapacity Number of preallocated element slots.
  @return A handle on the new array.
  */
H_DAWG_ARR_TYPE_NAME DAWG_ARR_FUNC_NAME(allocate)(unsigned int nInitialCapacity);


/**
  Reclaim the resources of the specified array.
  */
void DAWG_ARR_FUNC_NAME(destroy)(H_DAWG_ARR_TYPE_NAME hArr);


/**
  Fetch the first element of the specified array.

  The array must not be empty.
  */
_TYPE_ DAWG_ARR_FUNC_NAME(front)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch the last element of the specified array.

  The array must not be empty.
  */
_TYPE_ DAWG_ARR_FUNC_NAME(last)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch the element at the specified 0 based index of the specified array.

  The array must not be empty and nb el > nIdx.
  */
_TYPE_ DAWG_ARR_FUNC_NAME(get_el)(H_DAWG_ARR_TYPE_NAME hArr, unsigned int nIdx);

/**
  Set the element at the specified 0 based index of the specified array.

  The array must not be empty and nb el > nIdx.
  */
void DAWG_ARR_FUNC_NAME(set_el)(H_DAWG_ARR_TYPE_NAME hArr, unsigned int nIdx, _TYPE_ oEl);

/**
  Append the specified element at the end of the array.
  */
void DAWG_ARR_FUNC_NAME(push_back)(H_DAWG_ARR_TYPE_NAME hArr, _TYPE_ oNewEl);

/**
  Append the specified array at the end of the array.
  */
void DAWG_ARR_FUNC_NAME(append)(H_DAWG_ARR_TYPE_NAME hArr, H_DAWG_ARR_TYPE_NAME hArrToApp);

/**
  Fetch a classical "begin" iterator like in stl.
  */
_TYPE_* DAWG_ARR_FUNC_NAME(begin)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch a classical "one-before-begin" iterator like in stl.
  */
_TYPE_* DAWG_ARR_FUNC_NAME(before_begin)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch a classical "end" iterator like in stl.
  */
_TYPE_* DAWG_ARR_FUNC_NAME(end)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch the number of elements in the array.
  */
unsigned int DAWG_ARR_FUNC_NAME(size)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Fetch the total number of slots in the array.
  */
unsigned int DAWG_ARR_FUNC_NAME(capacity)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Determines whether the specified array is empty.
  */
dawg_bool_t DAWG_ARR_FUNC_NAME(is_empty)(H_DAWG_ARR_TYPE_NAME hArr);

/**
  Replaces all occurances of oElToRm by oElReplaceant in hArr.
  @return True iff at least one occrance of oElToRm has ben found and replaced by oElReplaceant.
  */
dawg_bool_t DAWG_ARR_FUNC_NAME(substitute)(H_DAWG_ARR_TYPE_NAME hArr, _TYPE_ oElToRm, _TYPE_ oElReplaceant);


/**
  Sorts in-place the content of the array, the order being defined by the functions "compar".

  @param compar The contents of the array are sorted in ascending order according to a comparison
                function pointed to by compar, which is called with two arguments that point to
                the objects being compared.
                The comparison function must return an integer less than, equal to, or greater than
                zero if the first argument is considered to be respectively less than, equal to, or
                greater than the second. If two members compare as equal, their order in the sorted
                array is undefined.
  */
void DAWG_ARR_FUNC_NAME(sort)(H_DAWG_ARR_TYPE_NAME hArr, int(*compar)(const void *, const void *));


///////////////////////////////////////
///////////////////////////////////////
//                                   //
// extern C END                      //
//                                   //
///////////////////////////////////////
///////////////////////////////////////
#ifdef __cplusplus
}
#endif
